//*****************************************************************************
// JFab (http://code.google.com/p/jfab)
// Copyright (c) 2011 JFab.org
// Admin jfab@jeffreythompson.net
//
// See the file "LICENSE.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//*****************************************************************************

package org.jfab.core.analyzer;

import org.jfab.core.comparator.CGClassComparator;
import org.jfab.core.comparator.CGConstructorComparator;
import org.jfab.core.comparator.CGEnumComparator;
import org.jfab.core.comparator.CGFieldComparator;
import org.jfab.core.comparator.CGInterfaceComparator;
import org.jfab.core.comparator.CGMethodComparator;
import org.jfab.core.comparator.CGMethodDeclarationComparator;
import org.jfab.core.comparator.ComparatorInjector;
import org.jfab.core.comparator.DefaultComparatorInjector;
import org.jfab.core.factory.CGAnnotationFactory;
import org.jfab.core.factory.CGClassFactory;
import org.jfab.core.factory.CGConstructorFactory;
import org.jfab.core.factory.CGEnumFactory;
import org.jfab.core.factory.CGEnumItemFactory;
import org.jfab.core.factory.CGFieldFactory;
import org.jfab.core.factory.CGInterfaceFactory;
import org.jfab.core.factory.CGMethodFactory;
import org.jfab.core.factory.CGParameterFactory;
import org.jfab.core.factory.CGTypeFactory;
import org.jfab.core.factory.DefaultFactoryInjector;
import org.jfab.core.factory.FactoryInjector;
import org.jfab.core.factory.StringFactory;
import org.jfab.core.model.CGTypeUtilities;
import org.jfab.core.model.DefaultModelInjector;
import org.jfab.core.model.ModelInjector;
import org.jfab.core.model.TypeFactory;

/**
 * Provides a default analyzer injector.
 */
public class DefaultAnalyzerInjector implements AnalyzerInjector
{
    /** Comparator injector. */
    private final ComparatorInjector _comparatorInjector;

    /** Factory injector. */
    private final FactoryInjector _factoryInjector;

    /** Model injector. */
    private final ModelInjector _modelInjector;

    /**
     * Construct this object.
     */
    public DefaultAnalyzerInjector()
    {
        this(new DefaultModelInjector(), new DefaultComparatorInjector(),
                new DefaultFactoryInjector());
    }

    /**
     * Construct this object with the given parameters.
     * 
     * @param modelInjector Model injector.
     * @param comparatorInjector Comparator injector.
     * @param factoryInjector Factory injector.
     */
    public DefaultAnalyzerInjector(final ModelInjector modelInjector,
            final ComparatorInjector comparatorInjector,
            final FactoryInjector factoryInjector)
    {
        _modelInjector = modelInjector;
        _comparatorInjector = comparatorInjector;
        _factoryInjector = factoryInjector;
    }

    @Override
    public ClassAnalyzer injectClassAnalyzer()
    {
        return new ClassAnalyzer(injectTypeFactory(), injectCGTypeUtilities(),
                injectCGTypeFactory(), injectStringFactory(),
                injectCGAnnotationFactory(), injectCGClassComparator(),
                injectCGClassFactory(), injectFieldAnalyzer(),
                injectConstructorAnalyzer(), injectMethodAnalyzer());
    }

    @Override
    public ConstructorAnalyzer injectConstructorAnalyzer()
    {
        return new ConstructorAnalyzer(injectTypeFactory(),
                injectCGTypeUtilities(), injectCGTypeFactory(),
                injectStringFactory(), injectCGAnnotationFactory(),
                injectCGConstructorComparator(), injectCGParameterFactory(),
                injectMethodAnalysisUtilities(), injectCGConstructorFactory());
    }

    @Override
    public EnumAnalyzer injectEnumAnalyzer()
    {
        return new EnumAnalyzer(injectTypeFactory(), injectCGTypeUtilities(),
                injectCGTypeFactory(), injectStringFactory(),
                injectCGAnnotationFactory(), injectCGEnumComparator(),
                injectCGEnumItemFactory(), injectCGEnumFactory(),
                injectFieldAnalyzer(), injectConstructorAnalyzer(),
                injectMethodAnalyzer());
    }

    @Override
    public FieldAnalyzer injectFieldAnalyzer()
    {
        return new FieldAnalyzer(injectTypeFactory(), injectCGTypeUtilities(),
                injectCGTypeFactory(), injectStringFactory(),
                injectCGAnnotationFactory(), injectCGFieldComparator(),
                injectCGFieldFactory());
    }

    @Override
    public InterfaceAnalyzer injectInterfaceAnalyzer()
    {
        return new InterfaceAnalyzer(injectTypeFactory(),
                injectCGTypeUtilities(), injectCGTypeFactory(),
                injectStringFactory(), injectCGAnnotationFactory(),
                injectCGInterfaceComparator(), injectCGInterfaceFactory(),
                injectFieldAnalyzer(), injectInterfaceMethodAnalyzer());
    }

    @Override
    public InterfaceMethodAnalyzer injectInterfaceMethodAnalyzer()
    {
        return new InterfaceMethodAnalyzer(injectTypeFactory(),
                injectCGTypeUtilities(), injectCGTypeFactory(),
                injectStringFactory(), injectCGAnnotationFactory(),
                injectCGMethodDeclarationComparator(),
                injectCGParameterFactory(), injectMethodAnalysisUtilities(),
                injectCGMethodFactory());
    }

    @Override
    public MethodAnalysisUtilities injectMethodAnalysisUtilities()
    {
        return new MethodAnalysisUtilities(injectCGTypeFactory());
    }

    @Override
    public MethodAnalyzer injectMethodAnalyzer()
    {
        return new MethodAnalyzer(injectTypeFactory(), injectCGTypeUtilities(),
                injectCGTypeFactory(), injectStringFactory(),
                injectCGAnnotationFactory(), injectCGMethodComparator(),
                injectCGParameterFactory(), injectMethodAnalysisUtilities(),
                injectCGMethodFactory());
    }

    /**
     * @return the comparatorInjector
     */
    private ComparatorInjector getComparatorInjector()
    {
        return _comparatorInjector;
    }

    /**
     * @return the factoryInjector
     */
    private FactoryInjector getFactoryInjector()
    {
        return _factoryInjector;
    }

    /**
     * @return the modelInjector
     */
    private ModelInjector getModelInjector()
    {
        return _modelInjector;
    }

    /**
     * @return a new annotation factory.
     */
    private CGAnnotationFactory injectCGAnnotationFactory()
    {
        return getFactoryInjector().injectCGAnnotationFactory();
    }

    /**
     * @return a new class comparator.
     */
    private CGClassComparator injectCGClassComparator()
    {
        return getComparatorInjector().injectCGClassComparator();
    }

    /**
     * @return a new class factory.
     */
    private CGClassFactory injectCGClassFactory()
    {
        return getFactoryInjector().injectCGClassFactory();
    }

    /**
     * @return a new constructor comparator.
     */
    private CGConstructorComparator injectCGConstructorComparator()
    {
        return getComparatorInjector().injectCGConstructorComparator();
    }

    /**
     * @return a new constructor factory.
     */
    private CGConstructorFactory injectCGConstructorFactory()
    {
        return getFactoryInjector().injectCGConstructorFactory();
    }

    /**
     * @return a new enum comparator.
     */
    private CGEnumComparator injectCGEnumComparator()
    {
        return getComparatorInjector().injectCGEnumComparator();
    }

    /**
     * @return a new enum factory.
     */
    private CGEnumFactory injectCGEnumFactory()
    {
        return getFactoryInjector().injectCGEnumFactory();
    }

    /**
     * @return a new enum item factory.
     */
    private CGEnumItemFactory injectCGEnumItemFactory()
    {
        return getFactoryInjector().injectCGEnumItemFactory();
    }

    /**
     * @return a new field comparator.
     */
    private CGFieldComparator injectCGFieldComparator()
    {
        return getComparatorInjector().injectCGFieldComparator();
    }

    /**
     * @return a new field factory.
     */
    private CGFieldFactory injectCGFieldFactory()
    {
        return getFactoryInjector().injectCGFieldFactory();
    }

    /**
     * @return a new interface comparator.
     */
    private CGInterfaceComparator injectCGInterfaceComparator()
    {
        return getComparatorInjector().injectCGInterfaceComparator();
    }

    /**
     * @return a new interface factory.
     */
    private CGInterfaceFactory injectCGInterfaceFactory()
    {
        return getFactoryInjector().injectCGInterfaceFactory();
    }

    /**
     * @return a new method comparator.
     */
    private CGMethodComparator injectCGMethodComparator()
    {
        return getComparatorInjector().injectCGMethodComparator();
    }

    /**
     * @return a new method declaration comparator.
     */
    private CGMethodDeclarationComparator injectCGMethodDeclarationComparator()
    {
        return getComparatorInjector().injectCGMethodDeclarationComparator();
    }

    /**
     * @return a new method factory.
     */
    private CGMethodFactory injectCGMethodFactory()
    {
        return getFactoryInjector().injectCGMethodFactory();
    }

    /**
     * @return a new code generator parameter factory.
     */
    private CGParameterFactory injectCGParameterFactory()
    {
        return getFactoryInjector().injectCGParameterFactory();
    }

    /**
     * @return a new type factory.
     */
    private CGTypeFactory injectCGTypeFactory()
    {
        return getFactoryInjector().injectCGTypeFactory();
    }

    /**
     * @return a new type utilities.
     */
    private CGTypeUtilities injectCGTypeUtilities()
    {
        return getModelInjector().injectCGTypeUtilities();
    }

    /**
     * @return a new string factory.
     */
    private StringFactory injectStringFactory()
    {
        return getFactoryInjector().injectStringFactory();
    }

    /**
     * @return a new type factory.
     */
    private TypeFactory injectTypeFactory()
    {
        return getModelInjector().injectTypeFactory();
    }
}
